﻿using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Text;
using System.Threading;

namespace WeighClient.Utils
{
    public class PortControlHelper
    {
        #region 字段/属性/委托
        /// <summary>  
        /// 串行端口对象  
        /// </summary>  
        private SerialPort sp;

        /// <summary>  
        /// 串口接收数据委托  
        /// </summary>  
        public delegate void ComReceiveDataHandler(string data);

        public ComReceiveDataHandler OnComReceiveDataHandler = null;

        /// <summary>  
        /// 端口名称数组  
        /// </summary>  
        public string[] PortNameArr { get; set; }

        /// <summary>  
        /// 串口通信开启状态  
        /// </summary>  
        public bool PortState { get; set; }

        /// <summary>  
        /// 编码类型  
        /// </summary>  
        public Encoding EncodingType { get; set; }
        #endregion

        private List<byte> buffer = new List<byte>(4096);

        #region 方法
        public PortControlHelper()
        {
            PortState = false;
            EncodingType = Encoding.ASCII;
            PortNameArr = SerialPort.GetPortNames();
            sp = new SerialPort();
            sp.DataReceived += new SerialDataReceivedEventHandler(DataReceived);
        }

        /// <summary>  
        /// 打开端口  
        /// </summary>  
        /// <param name="portName">端口名称</param>  
        /// <param name="boudRate">波特率</param>  
        /// <param name="dataBit">数据位</param>  
        /// <param name="stopBit">停止位</param>  
        /// <param name="timeout">超时时间</param>  
        public void OpenPort(string portName, int boudRate = 115200, int dataBit = 8, int stopBit = 1, int timeout = 5000)
        {
            try
            {
                sp.PortName = portName;
                sp.BaudRate = boudRate;
                sp.DataBits = dataBit;
                sp.StopBits = (StopBits)stopBit;
                sp.ReadTimeout = timeout;
                sp.Open();
                PortState = true;
            }
            catch (Exception e)
            {
                //throw e;
            }
        }

        /// <summary>  
        /// 关闭端口  
        /// </summary>  
        public void ClosePort()
        {
            try
            {
                sp.Close();
                PortState = false;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        /// <summary>  
        /// 发送数据  
        /// </summary>  
        /// <param name="sendData"></param>  
        public void SendData(string sendData)
        {
            try
            {
                sp.Encoding = EncodingType;
                sp.Write(sendData);
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public void SendHexData(string sendData)
        {
            try
            {
                byte[] bytes = ByteUtils.strToToHexByte(sendData);
                //sp.Encoding = EncodingType;
                sp.Write(bytes, 0, bytes.Length);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                throw e;
            }
        }

        public void SendByteData(byte[] sendData)
        {
            try
            {
                sp.Encoding = EncodingType;
                sp.Write(sendData, 0, sendData.Length);
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        /// <summary>  
        /// 接收数据回调用  
        /// </summary>  
        /// <param name="sender"></param>  
        /// <param name="e"></param>  
        private void DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                int n = sp.BytesToRead;
                byte[] buf = new byte[n];
                sp.Read(buf, 0, n);

                //1.缓存数据
                this.buffer.AddRange(buf);
                //2.完整性判断
                while (this.buffer.Count >= 5) //至少包含帧头（2字节）、长度（1字节）、校验位（1字节）；
                {
                    Console.WriteLine(ByteUtils.byteToHexStr(buf));
                    //2.1 查找数据头
                    if (this.buffer[0] == 0xFF && this.buffer[1] == 0xCC) //传输数据有帧头，用于判断
                    {
                        if (this.buffer[3] == 0x68)
                        {
                            if (this.buffer.Count < 37) break;
                            byte[] ReceiveBytes = new byte[37];
                            this.buffer.CopyTo(ReceiveBytes, 0);
                            this.buffer.RemoveRange(0, 37);

                            String hexString = ByteUtils.byteToHexStr(ReceiveBytes);
                            if (OnComReceiveDataHandler != null)
                            {
                                OnComReceiveDataHandler(hexString);
                            }
                        }
                        else if (this.buffer[3] == 0x69)
                        {
                            if (this.buffer.Count < 21) break;
                            byte[] ReceiveBytes = new byte[21];
                            this.buffer.CopyTo(ReceiveBytes, 0);
                            this.buffer.RemoveRange(0, 21);

                            String hexString = ByteUtils.byteToHexStr(ReceiveBytes);
                            if (OnComReceiveDataHandler != null)
                            {
                                OnComReceiveDataHandler(hexString);
                            }
                        }
                        else if (this.buffer[3] == 0x67)
                        {
                            if (this.buffer.Count < 13) break;
                            byte[] ReceiveBytes = new byte[13];
                            this.buffer.CopyTo(ReceiveBytes, 0);
                            this.buffer.RemoveRange(0, 13);

                            String hexString = ByteUtils.byteToHexStr(ReceiveBytes);
                            if (OnComReceiveDataHandler != null)
                            {
                                OnComReceiveDataHandler(hexString);
                            }
                        }
                        else if (this.buffer[3] == 0x62)
                        {
                            if (this.buffer.Count < 9) break;
                            byte[] ReceiveBytes = new byte[9];
                            this.buffer.CopyTo(ReceiveBytes, 0);
                            this.buffer.RemoveRange(0, 9);

                            String hexString = ByteUtils.byteToHexStr(ReceiveBytes);
                            if (OnComReceiveDataHandler != null)
                            {
                                OnComReceiveDataHandler(hexString);
                            }
                        }
                        else
                        {
                            Console.WriteLine("********");
                            this.buffer.RemoveRange(0, this.buffer.Count);
                        }
                    }
                    else
                    {
                        this.buffer.RemoveRange(0, this.buffer.Count);
                    }
                }
                /*
                byte[] buffer = new byte[sp.BytesToRead];
                sp.Read(buffer, 0, buffer.Length);

                String hexString = ByteUtils.byteToHexStr(buffer);

                string str = hexString;

                if (OnComReceiveDataHandler != null)
                {
                    OnComReceiveDataHandler(str);
                }*/
            }
            catch (Exception ex) { }
        }
        #endregion

        public static int openDoor(String com, int id)
        {
            int result = 0;
            try
            {
                PortControlHelper pchSend = new PortControlHelper(); ;
                //pchSend.OpenPort("COM2", 9600, 8, 1);
                pchSend.OpenPort(com, 9600, 8, 1);

                byte[] byte01 = new byte[10];
                byte01[0] = 0x48;
                byte01[1] = 0x3A;
                byte01[2] = 0x01;
                byte01[3] = 0x70;
                //byte01[4] = 0x01;
                if (id == 1)
                {
                    byte01[4] = 0x01;
                }
                else if (id == 2)
                {
                    byte01[4] = 0x02;
                }
                else if (id == 3)
                {
                    byte01[4] = 0x03;
                }
                else if (id == 4)
                {
                    byte01[4] = 0x04;
                }
                byte01[5] = 0x01;
                byte01[6] = 0x00;
                byte01[7] = 0x00;
                byte01[8] = 0x45;
                byte01[9] = 0x44;

                pchSend.SendByteData(byte01);

                Thread.Sleep(1000);

                byte01[5] = 0x00;
                pchSend.SendByteData(byte01);

                pchSend.ClosePort();
                result = 1;
            }
            catch (Exception ex)
            {
                result = 0;
            }
            return result;
        }

        public static int readInput(String com, int id)
        {
            int result = 0;
            try
            {
                PortControlHelper pchSend = new PortControlHelper(); ;
                pchSend.OpenPort(com, 9600, 8, 1);

                byte[] byte01 = new byte[15];
                byte01[0] = 0x48;
                byte01[1] = 0x3A;
                byte01[2] = 0x01;
                byte01[3] = 0x52;
                byte01[4] = 0x00;
                byte01[5] = 0x00;
                byte01[6] = 0x00;
                byte01[7] = 0x00;
                byte01[8] = 0x00;
                byte01[9] = 0x00;
                byte01[10] = 0x00;
                byte01[11] = 0x00;
                byte01[12] = 0xD5;
                byte01[13] = 0x45;
                byte01[14] = 0x44;
                
                pchSend.SendByteData(byte01);

                Thread.Sleep(1000);
                pchSend.ClosePort();
                result = 1;
            }
            catch (Exception ex)
            {
                result = 0;
            }
            return result;
        }
    }
}
